Source code for binarycpython.utils.email_utils

"""
Script to send an email when a function or simulation is finished.

https://leimao.github.io/blog/Python-Send-Gmail/
- I make use of the 'new authentication - less secure: app password' method
"""

import datetime
import smtplib
import ssl
import traceback
from email.message import EmailMessage


[docs]def send_email(config, body_text, subject): """ Main function to handle sending the email """ # Handle checking the configuration if not config["email_notifications_enabled"]: return corresponding_email = config["email_notifications_corresponding_email"] assert corresponding_email != "" # configuration port = 465 # For SSL smtp_server = "smtp.gmail.com" password = config["email_notifications_APP_password"] receiver_emails = [corresponding_email] + config[ "email_notifications_recipients" ] # Enter receiver address sender_email = corresponding_email # Enter your address # set content datetimestring = datetime.datetime.utcnow().isoformat() body_text = ( "Message from binary_c-python population sent on {}\n\n".format(datetimestring) + body_text ) # Set up email object for receiver_email in receiver_emails: msg = EmailMessage() msg.set_content(body_text) msg["Subject"] = subject msg["From"] = sender_email msg["To"] = receiver_email print( "sending email from {} to {} with subject {}".format( sender_email, receiver_email, subject ) ) # Allow for testing if not config.get("email_notifications_testing"): # Send email try: context = ssl.create_default_context() with smtplib.SMTP_SSL(smtp_server, port, context=context) as server: server.login(sender_email, password) server.send_message( msg, from_addr=sender_email, to_addrs=receiver_email ) except BaseException as error: print("An exception occurred: {}".format(error)) print(f"Exception Name: {type(error).__name__}") print(f"Exception Desc: {error}") print(f"Exception traceback: {traceback.print_exc()}") else: print("with body text:\n{}".format(body_text))
[docs]def send_error_email(config, error, traceback, message, class_object=None): """ Function to send a general error email. Optionally uses class object """ # class_object_text = ( "class {} population_id {}".format( class_object.__class__.__name__, config["_population_id"] ) if class_object is not None else "" ) subject = "binary_c-python population " + class_object_text + " failed" body_text = """ binary_c-python class: {} Exception Name: {} An exception occurred: {} Traceback: {} Message: {} """.format( class_object_text, error, type(error).__name__, traceback, message ) # Send the email send_email(config=config, body_text=body_text, subject=subject)
[docs]def send_succes_email(config, message, class_object=None): """ Function to send a general success email. Optionaly uses class object """ # class_object_text = ( "class {} population_id {}".format( class_object.__class__.__name__, config["_population_id"] ) if class_object is not None else "" ) subject = ( "binary_c-python population " + class_object_text + " completed without errors!" ) body_text = """ binary_c-python class: {} Message: {} """.format( class_object_text, message ) # Send the email send_email(config=config, body_text=body_text, subject=subject)
[docs]class Email_context_manager: def __init__(self, config, class_object): self.config = config self.class_object = class_object def __enter__(self): self.start = datetime.datetime.now() # We don't return anything here because we don't use the class instance anyway def __exit__(self, exc, value, exc_traceback): if not exc: self.class_object.send_success_email() else: actual_traceback_obj = traceback.format_exc() self.class_object.send_error_email(value, actual_traceback_obj)